package org.darcy.framework.generic;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.darcy.framework.model.PageData;
import org.darcy.framework.model.PageParam;
import org.springframework.beans.factory.annotation.Autowired;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

/**
 * GenericService的实现类, 其他的自定义 ServiceImpl, 继承自它,可以获得常用的增删查改操作, 未实现的方法有 子类各自实现
 */
public abstract class GenericServiceImpl<T> implements GenericService<T> {

	/**
	 * 日志对象
	 */
	protected Logger logger = LogManager.getLogger(this.getClass());

	/**
	 * 持久层对象
	 */
	@Autowired(required = false)
	protected GenericDao<T> dao;

	/**
	 * 判断对象是否是更新，id=null则是false
	 */
	private boolean isUpdate(T record) {
		Class<? extends Object> cls = record.getClass();
		Method getId;
		try {
			getId = cls.getDeclaredMethod("getId");
			if (getId != null) {
				Object id = getId.invoke(record);
				if (id == null) {
					return false;
				} else {
					return true;
				}
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 设置更新人员
	 */
	private void setUpdateInfo(T entity, Integer updateBy) {
		Class<? extends Object> cls = entity.getClass();
		Method setUpdateDate;
		Method setUpdateBy;
		try {
			setUpdateDate = cls.getDeclaredMethod("setUpdateTime", Date.class);
			if (setUpdateDate != null) {
				setUpdateDate.invoke(entity, new Date());
			}

			if (updateBy != null) {
				setUpdateBy = cls.getDeclaredMethod("setUpdateBy", String.class);
				if (setUpdateBy != null) {
					setUpdateBy.invoke(entity, updateBy);
				}
			}

		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 设置创建人员
	 */
	private void setCreateInfo(T entity, Integer createBy) {
		Class<? extends Object> cls = entity.getClass();
		Method setCreateDate;
		Method setCreateBy;
		try {
			setCreateDate = cls.getDeclaredMethod("setCreateTime", Date.class);
			if (setCreateDate != null) {
				setCreateDate.invoke(entity, new Date());
			}
			if (createBy != null) {
				setCreateBy = cls.getDeclaredMethod("setCreateBy", String.class);
				if (setCreateBy != null) {
					setCreateBy.invoke(entity, createBy);
				}
			}
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 插入对象
	 *
	 * @param T 对象
	 */
	public T insert(T record) {
		dao.insert(record);
		return record;
	}

	/**
	 * 更新对象
	 *
	 * @param record 对象
	 */
	public T update(T record) {
		dao.updateById(record);
		return record;
	}

	/**
	 * 批量更新
	 *
	 * @param list 对象列表
	 */
	public int updateBatch(List<T> list) {
		int count = 0;
		for (T record : list) {
			if (isUpdate(record))
				count += dao.insert(record);
			else
				count += dao.updateById(record);
		}
		return count;
	}

	/**
	 * 通过主键, 删除对象
	 *
	 * @param id 主键
	 */
	public int delete(Object id) {
		return dao.deleteById((Serializable) id);
	}

	/**
	 * 批量删除
	 *
	 * @param idList 主键集合
	 */
	public int deleteByIds(Collection<?> idList) {
		return dao.deleteBatchIds(idList);
	}

	/**
	 * 批量删除
	 *
	 * @param queryWrapper 查询条件
	 */
	public int deleteBatch(Wrapper<T> queryWrapper) {
		return dao.delete(queryWrapper);
	}

	public long count(Wrapper<T> queryWrapper) {
		return dao.selectCount(queryWrapper);
	}

	/**
	 * 通过主键, 查询对象
	 *
	 * @param id 主键
	 * @return
	 */
	public T getById(Object id) {
		return dao.selectById((Serializable) id);
	}

	/**
	 * 批量查询
	 *
	 * @param idList 主键列表
	 * @return
	 */
	public List<T> getByIds(Collection<?> idList) {
		return dao.selectBatchIds((Collection<? extends Serializable>) idList);
	}

	/**
	 * 根据条件查询列表数据
	 * 
	 * @param queryWrapper
	 * @return
	 */
	public T getOne(Wrapper<T> queryWrapper) {
		return dao.selectOne(queryWrapper);
	}

	/**
	 * 根据条件查询列表数据
	 * 
	 * @param queryWrapper
	 * @return
	 */
	public List<T> getList(Wrapper<T> queryWrapper) {
		return dao.selectList(queryWrapper);
	}

	/**
	 * 根据条件查询列表数据(分页)
	 * 
	 * @param page         分页条件
	 * @param queryWrapper 查询条件
	 * @return
	 */
	public IPage<T> getPage(IPage<T> page, Wrapper<T> queryWrapper) {
		return dao.selectPage(page, queryWrapper);
	}

	@Override
	public PageData<T> getPageData(PageParam param) {
		QueryWrapper wrapper = new QueryWrapper();
		IPage page = new Page(param.getQuery().getPageNum(), param.getQuery().getPageSize());
		IPage list = this.getPage(page, wrapper);
		PageData data = new PageData(list, param);
		return data;
	}

}
